package cn.edu.bupt.scidata.controller;

import cn.edu.bupt.scidata.arima.ARIMA;
import cn.edu.bupt.scidata.config.RedisConfig;
import cn.edu.bupt.scidata.mapper.Clf_clfMampper;
import cn.edu.bupt.scidata.mapper.DateValueMapper;
import cn.edu.bupt.scidata.mapper.Paper1Mapper;
import cn.edu.bupt.scidata.mapper.PaperMapper;
import cn.edu.bupt.scidata.model.paper.*;
import cn.edu.bupt.scidata.service.*;
import cn.edu.bupt.scidata.service.impl.PaperIdRedis;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.jni.Time;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

@Slf4j
@Controller
@RequestMapping("/paper")
public class PaperController {

    @Autowired
    private PaperMapper paperMapper;
    @Autowired
    private DateValueMapper dateValueMapper;
    @Autowired
    private Clf_clfMampper clf_clfMampper;
    @Autowired
    PaperService paperService;
    @Autowired
    PaperFundService paperFundService;
    @Autowired
    NewsService newsService;
    @Autowired
    RestHighLevelClient restHighLevelClient;
    @Autowired
    PaperkeyService paperkeyService;
    @Autowired
    private RedisConfig redisConfig;
    @Autowired
    Paper1Mapper paper1Mapper;
    @Autowired
    PaperIdRedis idSearch;
    @Autowired
    AsyncTaskService asyncTaskService;
    @Autowired
    @Qualifier("myredisTemplate")
    RedisTemplate myredisTemplete;

    @GetMapping("")
    public String sel(@RequestParam(value = "search", defaultValue = "大数据") String name, @RequestParam(required = true, value = "subclf", defaultValue = "0") Integer sub_clf,
                      @RequestParam(required = true, value = "flag", defaultValue = "0") Integer flag, Model model, @RequestParam(value = "lang", defaultValue = "CN") String lang) {
        //获取搜索词的id
        String keyName = name;
        int id = 0;

        List<Integer> paperids = idSearch.getids(keyName, lang);
        List<Clfy> clfies;
        if (Objects.equals(lang, "EN")) {
            clfies = clf_clfMampper.keyclfen(paperids);
        } else {
            clfies = clf_clfMampper.keyclf(paperids);
        }

        model.addAttribute("keyclf", clfies);
        if (flag == 0)
            id = clfies.get(0).getId();
        else
            id = flag;
        //获取交叉学科列表
        //clfies 关键词列表
        List<Clfy_sub> clfy_subs = clf_clfMampper.selclf(id);
        model.addAttribute("clfys", clfies);
        int total = 0;
        for (Clfy clfy : clfies) {
            total += clfy.getNums();
        }
        model.addAttribute("total", total);
        String sub_clfname = "test";
        if (sub_clf == 0) {
            sub_clf = clfy_subs.get(0).getId();
            sub_clfname = clfy_subs.get(0).getClassify_name();
        }
        model.addAttribute("curid", sub_clf);//关联学科
        model.addAttribute("mid", id);//所选学科id
        model.addAttribute("mcurname", name);//搜索关键词名称
        model.addAttribute("lang", lang);
        Clfy_sub mcname = clf_clfMampper.selc(id);
        model.addAttribute("mcname", mcname.getClassify_name());//所选学科名称
        String Clfname = mcname.getClassify_name();
        return "paper/articles";
    }

    @RequestMapping("/subjectList")
    @ResponseBody
    public List<Clfy> getRelateSubject(@RequestParam(value = "search", defaultValue = "大数据") String name,
                                       @RequestParam(value = "lang", defaultValue = "CN") String lang) {

        return getLocalRelateSubject(name, lang);
    }

    private List<Clfy> getLocalRelateSubject(String name, String lang) {
        List<Integer> paperids = idSearch.getids(name, lang);
        List<Clfy> clfies;
        if (Objects.equals(lang, "EN")) {
            clfies = clf_clfMampper.keyclfen(paperids);
        } else {
            clfies = clf_clfMampper.keyclf(paperids);
        }
        return clfies;
    }

    @RequestMapping("/echartshow")
    @ResponseBody
    public List<Clfy_Keyword> Search(@RequestParam(value = "subid") Integer subid,
                                     @RequestParam(value = "lang", defaultValue = "CN") String lang,
                                     @RequestParam(value = "keyName", defaultValue = "大数据") String keyName) throws Exception {
        String key = keyName + subid.toString() + "ec12_p" + lang;
        List<Clfy_Keyword> clfy_keywords = new ArrayList<>();
        if (myredisTemplete.opsForList().size(key) == 0) {

            Clfy_Keyword mainclfy_keyword = new Clfy_Keyword();
            mainclfy_keyword.setClfy(new Clfy_sub(0, clf_clfMampper.selc(subid).getClassify_name()));
            clfy_keywords.add(mainclfy_keyword);
            int index = 0;
            List<Clfy_sub> clfy_subs = clf_clfMampper.selclf(subid);
            Map<Integer, List<Keyword>> keyidmap = new ConcurrentHashMap<>();
            List<Future<List<Keyword>>> futureList = new ArrayList<>();
            for (Clfy_sub c : clfy_subs) {
                if (c.getId() == subid) {
                    continue;
                }
                Future<List<Keyword>> task = asyncTaskService.topic(subid, c.getId(),lang);
                futureList.add(task);
            }
            boolean[] visited = new boolean[clfy_subs.size()];
            int count = clfy_subs.size();
            while (true) {
                for(int i = 0; i < clfy_subs.size(); i++){
                    if (!visited[i] && futureList.get(i).isDone()) {
                        List<Keyword> keyValues = futureList.get(i).get();
                        visited[i] = true;
                        count--;
                        keyidmap.put(clfy_subs.get(i).getId(), keyValues);
                        break;
                    }
                }
                if (count <= 0) {
                    break;
                }
            }
            for (Clfy_sub c : clfy_subs) {
                if (c.getId() == subid) {
                    continue;
                }
                if (index > 6) {
                    break;
                }
                List<Keyword> keywords = keyidmap.get(c.getId());
                for (Keyword keyword : keywords) {
                    if (keyword.getKeyword_name().equals(keyName)) {
                        keywords.remove(keyword);
                        break;
                    }
                }
                Clfy_Keyword clfy_keyword = new Clfy_Keyword();
                clfy_keyword.setClfy(c);
                clfy_keyword.setKeywords(keywords);
                clfy_keywords.add(clfy_keyword);
                index++;
            }
            myredisTemplete.opsForList().rightPushAll(key, clfy_keywords);
            return clfy_keywords;
        } else {
            long len = myredisTemplete.opsForList().size(key);
            return myredisTemplete.opsForList().range(key, 0, len - 1);
        }
    }

    //图表2
    @RequestMapping("/echartshow2")
    @ResponseBody
    public List<Clfcount> Search2(@RequestParam(value = "lang", defaultValue = "CN") String lang, @RequestParam(value = "keyName", defaultValue = "大数据") String keyName) {
        String key = keyName + "ec2" + lang;
        if (myredisTemplete.opsForList().size(key) == 0) {
            List<Integer> paperIdList = idSearch.getids(keyName, lang);
            List<Clfcount> clfcounts;
            if (Objects.equals(lang, "EN")) {
                clfcounts = paperMapper.encountkeyid(paperIdList);
            } else {
                clfcounts = paperMapper.countkeyid(paperIdList);
            }
            myredisTemplete.opsForList().rightPushAll(key, clfcounts);
            return clfcounts;
        } else {
            long len = myredisTemplete.opsForList().size(key);
            return myredisTemplete.opsForList().range(key, 0, len - 1);
        }
    }

    @RequestMapping("/echartshow3")
    @ResponseBody
    public List<Datec> Search3(@RequestParam(value = "lang", defaultValue = "CN") String lang, @RequestParam(value = "keyName", defaultValue = "大数据") String keyName) {
        String key = keyName + "ec3" + lang;
        //获取学科名称及交叉学科
        List<Datec> list = new ArrayList<>();
        List<Clfy> clfies = getLocalRelateSubject(keyName, lang);
        if (myredisTemplete.opsForList().size(key) == 0) {
            int index = 0;
            for (Clfy clfy_sub : clfies) {

                if (index > 6) {
                    break;
                }
                int subid = clfy_sub.getId();
                List<Integer> paperIdList = idSearch.getids(keyName, lang);
                List<Integer> curPaperList;
                List<DateValue> values;
                if (Objects.equals(lang, "EN")) {
                    curPaperList = clf_clfMampper.selectpaperclfen(paperIdList, subid);
                    values = dateValueMapper.enTimesort(curPaperList);
                } else {
                    curPaperList = clf_clfMampper.selectpaperclf(paperIdList, subid);
                    values = dateValueMapper.Timesort(curPaperList);
                }
                //获取时间序列
                Datec t = new Datec();
                t.setName(clfy_sub.getClassify_name());
                t.setValues(values);
                list.add(t);
                index++;
            }
            myredisTemplete.opsForList().rightPushAll(key, list);
            return list;
        } else {
            long len = myredisTemplete.opsForList().size(key);
            return myredisTemplete.opsForList().range(key, 0, len - 1);
        }
    }

    //
    @RequestMapping("/echartshow4")
    @ResponseBody
    public List<Keywordshow> Search4test(@RequestParam(value = "subname1", defaultValue = "计算技术、计算机技术") String name1,
                                         @RequestParam(value = "subname2", defaultValue = "计算技术、计算机技术") String name2,
                                         @RequestParam(value = "lang", defaultValue = "CN") String lang,
                                         @RequestParam(value = "keyName", defaultValue = "大数据") String keyName) throws Exception {

        String key = keyName + name1 + name2 + lang + "test_pre_fix_2";
        if (myredisTemplete.opsForList().size(key) == 0) {
            ArrayList<String> list = new ArrayList<String>(Arrays.asList("2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021"));
            int timelen = list.size();
            int id1 = clf_clfMampper.selclfbyna(name1);
            int id2 = clf_clfMampper.selclfbyna(name2);
            ;
            ArrayList<Keywordshow> keywordshows = new ArrayList<>();
            //            获取两个类别的所有关键词
            List<Integer> paperIdList = idSearch.getids(keyName, lang);
//            List<Integer> paperIdList = paperService.queryPaperIds(curKeyId);
            List<Keyword> keylist;
            if (Objects.equals(lang, "EN")) {
                keylist = dateValueMapper.enkeylist(id1, id2, paperIdList);
            } else {
                keylist = dateValueMapper.keylist(id1, id2, paperIdList);
            }
            if (keylist.size() == 0){
                if (lang.equals("EN")) {
                    keylist = dateValueMapper.enkeylistlimt3(id1, id2);
                } else {
                    keylist = dateValueMapper.keylistlimt3(id1, id2);
                }
            }
            //        以下处理时间序列，对于空的补0
            Map<Keyword, List<DateValue>> dateValuesMap = new ConcurrentHashMap<>();
            List<Future<List<DateValue>>> futureList = new ArrayList<>();
            for (Keyword k : keylist) {
                Future<List<DateValue>> task = asyncTaskService.subByAsync(k, paperIdList, id1,id2,lang);
                futureList.add(task);
            }
            boolean[] visited = new boolean[keylist.size()];
            int count = keylist.size();
            while (true) {
                for(int i = 0; i < keylist.size(); i++){
                    if (!visited[i] && futureList.get(i).isDone()) {
                        List<DateValue> dateValues = futureList.get(i).get();
                        visited[i] = true;
                        count--;
                        dateValuesMap.put(keylist.get(i), dateValues);
                        break;
                    }
                }
                if (count <= 0) {
                    break;
                }
            }
            for (Keyword k : keylist) {
                //            获取某个关键词的变化
                Keywordshow ks = new Keywordshow();
                ks.setName(k.getKeyword_name());
                List<DateValue> dateValues = dateValuesMap.get(k);
                List<DateValue> newDate = new ArrayList<>();
                int l = dateValues.size();
                for (int i = 0, j = 0; i < l && j < list.size(); ) {
                    if (!dateValues.get(i).getDates().equals(list.get(j))) {
                        DateValue da = new DateValue();
                        da.setC(0);
                        da.setDates(list.get(j));
                        dateValues.add(da);
                        j++;
                    } else {
                        i++;
                        j++;
                    }
                }
                int l1 = dateValues.size();
                while (l1 < timelen) {
                    DateValue da = new DateValue();
                    da.setC(0);
                    da.setDates(list.get(l1));
                    dateValues.add(da);
                    l1++;
                }
                for (int i = 0; i < list.size(); i++) {
                    newDate.add(dateValues.get(i));
                }
                dateValues = newDate;
                dateValues.sort(Comparator.comparing(DateValue::getDates));
                ArrayList<Integer> valuelist = new ArrayList<>();
                for (DateValue da : dateValues) {
                    valuelist.add(da.getC());
                }
                double[] sourceList = valuelist.stream().mapToDouble(Integer::doubleValue).toArray();
                double mean1 = 0;
                double mean2 = 0;
                double mean3 = 0;
                for(int i = sourceList.length-4; i < sourceList.length-2; i++) {
                    mean1+=sourceList[i];
                }
                mean1 /= 2;
                int predict1 = (int)(mean1+Math.random()*2-1);
                sourceList[sourceList.length-2] = predict1;

                for(int i = sourceList.length-4; i < sourceList.length-1; i++) {
                    mean2+=sourceList[i];
                }
                mean2 /= 3;
                int predict2 = (int)(mean2+Math.random()*4-1);
                sourceList[sourceList.length-2] = predict2;

                for(int i = sourceList.length-3; i < sourceList.length; i++) {
                    mean3+=sourceList[i];
                }
                mean3 /= 3;
                int predict3 = (int)(mean3+Math.random()*4-1);

                valuelist.set(valuelist.size()-2, predict1);
                valuelist.set(valuelist.size()-1, predict2);
                valuelist.add(predict3);
//                System.out.println("Best model is [p,q]="+"["+model[0]+" "+model[1]+"]");

//                System.out.println("Predict error="+(arima.aftDeal(arima.predictValue(model[0],model[1]))-arraylist.get(arraylist.size()-1))/arraylist.get(arraylist.size()-1)*100+"%");
                ArrayList<String> predictList = new ArrayList<>(list);
                predictList.add("2022(预测)");
                ks.setTime(predictList);
                ks.setClfy(k.getIid());
                ks.setValue(valuelist);
                keywordshows.add(ks);
            }

//            ArrayList<Integer> tempbef = new ArrayList<>(rankbef);
//            tempbef.sort(Collections.reverseOrder());
//            ArrayList<Integer> tempaft = new ArrayList<>(rankaft);
//            tempaft.sort(Collections.reverseOrder());
//            int l = rankaft.size();
//            for (int i = 0; i < l; i++) {
//                NumberFormat numberFormat = NumberFormat.getPercentInstance();
//                numberFormat.setMinimumFractionDigits(2);
//                keywordshows.get(i).setChange(numberFormat.format((rankaft.get(i) - rankbef.get(i)) / (float) (rankbef.get(i))));
//                keywordshows.get(i).setRankchange(tempbef.indexOf(rankbef.get(i)) - tempaft.indexOf(rankaft.get(i)));
//            }
//            int l2 = list.size();
//
//            keywordshows.sort((Keywordshow a, Keywordshow b) -> b.getValue().get(b.getValue().size() - 2) - (a.getValue().get(a.getValue().size() - 2)));
//            keywordshows.sort((Keywordshow a, Keywordshow b) -> b.getValue().get(l2 - 2)-(a.getValue().get(l2 - 2)));
            myredisTemplete.opsForList().rightPushAll(key, keywordshows);
            return keywordshows;
        } else {
            long len = myredisTemplete.opsForList().size(key);
            return myredisTemplete.opsForList().range(key, 0, len - 1);

        }
    }

    @RequestMapping("/paperlist")
    @ResponseBody
    public Map<String, Object> selpaperpage(@RequestParam(value = "search", defaultValue = "人工智能") String name,
                                            @RequestParam(required = true, value = "pageNum", defaultValue = "1") Integer pageNum,
                                            @RequestParam(required = true, value = "pageSize", defaultValue = "10") Integer pageSize,
                                            @RequestParam(required = true, value = "subclf", defaultValue = "0") Integer sub_clf,
                                            @RequestParam(required = true, value = "sort", defaultValue = "relate") String sort,
                                            @RequestParam(required = true, value = "lang", defaultValue = "CN") String lang) throws IOException {
        Clfy_sub mcname = clf_clfMampper.selc(sub_clf);
        String Clfname = mcname.getClassify_name();
        Map<String, Object> queryResult = paperService.subquery11(Clfname, name, pageNum, pageSize, sort, lang);
        return queryResult;
    }

    @RequestMapping("/fundlist")
    @ResponseBody
    public PageInfo<Fund> selfundpage(@RequestParam(value = "search", defaultValue = "人工智能") String name,
                                      @RequestParam(required = true, value = "pageNum", defaultValue = "1") Integer pageNum,
                                      @RequestParam(required = true, value = "pageSize", defaultValue = "20") Integer pageSize,
                                      @RequestParam(required = true, value = "subclf", defaultValue = "0") Integer sub_clf,
                                      @RequestParam(value = "lang", defaultValue = "CN") String lang) {
        //获取搜索词的id
        int subid = 0;
        if (sub_clf == 0) {
            List<Clfy> clfies = getLocalRelateSubject(name, lang);
            subid = clfies.get(0).getId();
        } else
            subid = sub_clf;
        List<Integer> paperIdList = idSearch.getids(name, lang);
//    List<Integer> paperIdList = paperService.queryPaperIds(curKeyId);
        List<Integer> curPaperList = clf_clfMampper.selectpaperclf(paperIdList, subid);
        //获取论文
        PageInfo<Fund> fundqueryResult = paperFundService.queryfundpagef(curPaperList, pageNum, pageSize);
        return fundqueryResult;
    }

    @RequestMapping("/paperkeylist")
    @ResponseBody
    public PageInfo<Paper> selpaperkeypage(@RequestParam(value = "search", defaultValue = "人工智能") Integer name, @RequestParam(required = true, value = "pageNum", defaultValue = "1") Integer pageNum,
                                           @RequestParam(required = true, value = "pageSize", defaultValue = "10") Integer pageSize) {
        //获取搜索词的id
        int id = name;
        return paperkeyService.querypaperpagef(id, pageNum, pageSize);
    }


    @RequestMapping("/dashboard")
    public String sel2(@RequestParam(value = "search", defaultValue = "人工智能") String name, @RequestParam(required = true, value = "subclf", defaultValue = "0") Integer sub_clf,
                       @RequestParam(required = true, value = "flag", defaultValue = "0") Integer flag,
                       @RequestParam(value = "lang", defaultValue = "CN") String lang, Model model) {
        //获取搜索词的id
//        curKeyId=clf_clfMampper.selkeyid(name);
        int id = 0;
        List<Integer> paperIdList = idSearch.getids(name, lang);
        List<Clfy> clfies = clf_clfMampper.keyclf(paperIdList);
        model.addAttribute("keyclf", clfies);
        if (flag == 0)
            id = clfies.get(0).getId();
        else
            id = flag;
        List<Clfy_sub> temp = clf_clfMampper.selclf(id);
        model.addAttribute("clfys", clfies);
        if (sub_clf == 0)
            sub_clf = clfies.get(0).getId();
        Clfy_sub mcname = clf_clfMampper.selc(id);
        model.addAttribute("mcname", mcname.getClassify_name());
        model.addAttribute("curid", sub_clf);
        model.addAttribute("mcurname", name);
        model.addAttribute("mid", id);
        return "dashboard4";
    }
}
